import time
from enum import Enum

from ..exception.TestException import TestException
from ..common.ui.PageElement import PageElement
from selenium.webdriver.remote.webdriver import WebDriver
from ..common.ui.Selector import Selector
from ..exception.errorcode import ErrorCode
from robot.api import logger
from Lib.zcm.assistant.FwVariables import get_value, get_bool_value


class Alert(PageElement):

    def __init__(self, driver: WebDriver):
        super(Alert, self).__init__(driver=driver, selector_str=self.get_modal_class(),
                                    selector_type=Selector.CLASS_NAME)

    def click(self, button='OK', prompt_text=None):
        """
        自动获取当前页面有哪些fish alert类型，选择button点击，如果
        :param button:
        :return:
        """
        script = "$(arguments[0]).children('.modal-footer').children('{0}').click()"
        if 'OK' == button.upper():
            script = script.format(self.get_ok_btn_class())
        elif 'CANCEL' == button.upper():
            script = script.format(self.get_cancel_btn_class())
        else:
            raise TestException.by_error_code(ErrorCode.ALERT_NOT_SUPPORT_BUTTON, value=button.upper())
        self.input_prompt_text(prompt_text)
        self._execute_script(script, self._get_web_element())

    def input_prompt_text(self, prompt_text):
        if prompt_text is not None:
            raise TestException.by_error_code(ErrorCode.ALERT_NOT_SUPPORT_INPUT_TEXT)

    def get_modal_class(self) -> str:
        pass

    def get_ok_btn_class(self) -> str:
        pass

    def get_cancel_btn_class(self) -> str:
        raise TestException.by_error_code(ErrorCode.ALERT_NOT_SUPPORT_CANCEL_BUTTON)


class AlertInfo(Alert):

    def get_modal_class(self) -> str:
        return 'modal-info'

    def get_ok_btn_class(self) -> str:
        return '.btn-info'


class AlertSuccess(Alert):

    def get_modal_class(self) -> str:
        return 'modal-success'

    def get_ok_btn_class(self) -> str:
        return '.btn-success'


class AlertWarn(Alert):

    def get_modal_class(self) -> str:
        return 'modal-warning'

    def get_ok_btn_class(self) -> str:
        return '.btn-warning'


class AlertError(Alert):

    def get_modal_class(self) -> str:
        return 'modal-danger'

    def get_ok_btn_class(self) -> str:
        return '.btn-danger'


class AlertConfirm(Alert):

    def get_modal_class(self) -> str:
        return 'modal-confirm'

    def get_ok_btn_class(self) -> str:
        return '.btn-primary'

    def get_cancel_btn_class(self) -> str:
        return '.btn-default'

    def input_prompt_text(self, text=''):
        """
        prompt 和confirm定位元素一样，只是多了个填入文字input
        :param text:
        :return:
        """
        script = "$(arguments[0]).children('.modal-body').children('.form-control').val('{0}')".format(text)
        self._execute_script(script, self._get_web_element())


def process_fish_modal_dialog_alert(driver: WebDriver, button='OK', prompt_text=None):
    flag = driver.execute_script("var flag=false; var ele=undefined; "
                                 "$('.ui-dialog.ui-draggable')"
                                 ".each("
                                 "function(index, e) {"
                                 "var attr_class = $(e).attr('class'); "
                                 "if(attr_class.indexOf('modal') != -1) { ele= $(e);}"
                                 "});"
                                 "if(ele) {flag=true}"
                                 "return true ")
    alert = None
    if flag:
        if driver.execute_script("return $('.ui-dialog.ui-draggable.modal-info').size()") == 1:
            alert = AlertInfo(driver)
        elif driver.execute_script("return $('.ui-dialog.ui-draggable.modal-success').size()") == 1:
            alert = AlertSuccess(driver)
        elif driver.execute_script("return $('.ui-dialog.ui-draggable.modal-warn').size()") == 1:
            alert = AlertWarn(driver)
        elif driver.execute_script("return $('.ui-dialog.ui-draggable.modal-danger').size()") == 1:
            alert = AlertError(driver)
        elif driver.execute_script("return $('.ui-dialog.ui-draggable.modal-confirm').size()") == 1:
            alert = AlertConfirm(driver)
        if alert is None:
            raise TestException.by_error_code(ErrorCode.ALERT_NOT_FIND)
        else:
            alert.click(button=button, prompt_text=prompt_text)
    else:
        raise TestException.by_error_code(ErrorCode.ALERT_NOT_FIND)


def check_page_error(zcm_obj):
    driver = zcm_obj._drivers.current
    flag = driver.execute_script("var flag=false; var ele=undefined; "
                                 "$('.ui-dialog.ui-draggable')"
                                 ".each("
                                 "function(index, e) {"
                                 "var attr_class = $(e).attr('class'); "
                                 "if(attr_class.indexOf('modal') != -1) { ele= $(e);}"
                                 "});"
                                 "if(ele) {flag=true}"
                                 "return true ")
    logger.info("flag:{}".format(flag))
    if flag:
        size = driver.execute_script("return $('.ui-dialog.ui-draggable.modal-danger').size()")
        logger.info("size:{}".format(size))
        if size == 1:
            return False
    return True


class Check_page_error_enum(Enum):
    BEFORE = "BEFORE"
    AFTER = "AFTER"
    ALL = "ALL"


def check_page_error_before_operate(zcm_obj):
    is_check_page_error = get_value("GENERAL", "IS_CHECK_PAGE_ERROR", False)
    if is_check_page_error in [Check_page_error_enum.ALL.value, Check_page_error_enum.BEFORE.value]:
        check_page_error_with_operate(zcm_obj)


def check_page_error_after_operate(zcm_obj):
    is_check_page_error = get_value("GENERAL", "IS_CHECK_PAGE_ERROR", False)
    if is_check_page_error in [Check_page_error_enum.ALL.value, Check_page_error_enum.AFTER.value]:
        check_page_error_with_operate(zcm_obj)


def check_page_error_with_operate(zcm_obj):
    check_page_error_wait_time = int(get_value("GENERAL", "CHECK_PAGE_ERROR_WAIT_TIME", 10))
    timer = 0
    inspection_time = 1
    while True:
        check_result = check_page_error(zcm_obj)
        if not check_result:
            raise Exception("page error!")
        time.sleep(inspection_time)
        timer += inspection_time
        # 超过了设置时间还没有报错，则视为正常，直接return
        if timer > check_page_error_wait_time:
            return
